#pragma once
#include "CoordSys.h"

class CMeasureStation
{
  friend class boost::serialization::access;
public:
  enum ImageFormat {
    kBmp  = 0,
    kPng  = 1,
    kJpeg = 2,
    kTiff = 3,

    kImageFormatButt
  };

  static const TCHAR* ImageFormatToString(int image_format);
  static int ParseImageFormat(const CString &str_image_format);

public:
  CMeasureStation(void);
  CMeasureStation(const tstring& Name, const tstring& Camera);
  ~CMeasureStation(void);

public:
  void Init(void);
  void Reset(void);
  long BuildCoordSys(CCoordSys& cs) const;
  long Process(CWnd* view, CommandSource CmdSource);

  void CreateImageFolder(void);
  void DeleteImageFolder(void);
  void DeleteAllImages(void);

public:
  long AddLine(const tstring& lineName);
  long DeleteLine(const tstring& lineName);
  void ClearLines(void) { lines_.clear(); }
  void ChangeLineName(const tstring& oldName, const tstring& newName);

  long AddArc(const tstring& arcName);
  long DeleteArc(const tstring& arcName);
  void ClearArcs(void) { arcs_.clear(); }
  void ChangeArcName(const tstring& oldName, const tstring& newName);

  long AddBox(const tstring& boxName);
  long DeleteBox(const tstring& boxName);
  void ClearBoxs(void) { boxs_.clear(); }
  void ChangeBoxName(const tstring& oldName, const tstring& newName);

  long AddEtch(const tstring& etchName);
  long DeleteEtch(const tstring& etchName);
  void ClearEtchs(void) { etchs_.clear(); }

public:
  const tstring& Name(void) const { return name_; }
  void set_name(const tstring& val) { name_ = val; }

  const tstring& cmd_name(void) const { return cmd_name_; }
  void set_cmd_name(const tstring& val) { cmd_name_ = val; }

  const tstring& camera(void) const { return camera_; }
  void set_camera(const tstring& val) { camera_ = val; }

  const tstring& model(void) const { return model_; }
  void set_model(const tstring& val) { model_ = val; }

  int gain(void) const { return gain_; }
  void set_gain(int val) { gain_ = val; }

  int shutter(void) const { return shutter_; }
  void set_shutter(int val) { shutter_ = val; }

  int save_ok(void) const { return save_ok_; }
  void set_save_ok(int val) { save_ok_ = val; }

  int save_ng(void) const { return save_ng_; }
  void set_save_ng(int val) { save_ng_ = val; }

  int num_oks(void) const { return num_oks_; }
  int num_ngs(void) const { return num_ngs_; }

  int num_max_to_save(void) const { return num_max_to_save_; }
  void set_num_max_to_save(int val) { num_max_to_save_ = val; }

  int min_save_interval(void) const { return min_save_interval_; }
  void set_min_save_interval(int val) { min_save_interval_ = val; }

  int save_always_from_serial(void) const { return save_always_from_serial_; }
  void set_save_always_from_serial(int val) { save_always_from_serial_ = val; }

  const char* save_format_string(void) const;
  const char* save_format_extension(void) const;
  int save_format(void) const { return save_format_; }
  void set_save_format(int val) { save_format_ = val; }

  int find_model(void) const { return find_model_; }
  void set_find_model(int val) { find_model_ = val; }

  int build_coord_sys(void) const { return build_coord_sys_; }
  void set_build_coord_sys(int val) { build_coord_sys_ = val; }

  const tstring& dynamic_coord_sys(void) const { return dynamic_coord_sys_; }
  void set_dynamic_coord_sys(const tstring& val) { dynamic_coord_sys_ = val; }

  const CCoordSys& template_coord_sys(void) const { return template_coord_sys_; }
  void set_template_coord_sys(const CCoordSys& val, bool fireSignal);

  int num_lines(void) const { return static_cast<int>(lines_.size()); }
  const tstring& line(int index) const { return lines_.at(index); }

  int num_arcs(void) const { return static_cast<int>(arcs_.size()); }
  const tstring& arc(int index) const { return arcs_.at(index); }

  int num_boxs(void) const { return static_cast<int>(boxs_.size()); }
  const tstring& box(int index) const { return boxs_.at(index); }

  int num_etchs(void) const { return static_cast<int>(etchs_.size()); }
  const tstring& etch(int index) const { return etchs_.at(index); }

private:
  void SaveStationImage(bool ok, CommandSource cmd_source);
  void SaveOkImage(boost::chrono::steady_clock::time_point save_time);
  void SaveNgImage(boost::chrono::steady_clock::time_point save_time);
  boost::chrono::steady_clock::time_point previous_save_time_;

private:
  tstring               name_;
  tstring               cmd_name_;
  tstring               camera_;
  tstring               model_;
  int                   gain_;
  int                   shutter_;
  int                   save_ok_;
  int                   save_ng_;
  int                   num_oks_;
  int                   num_ngs_;
  int                   num_max_to_save_;
  int                   min_save_interval_;
  int                   save_always_from_serial_;
  int                   save_format_;
  int                   find_model_;
  int                   build_coord_sys_;
  tstring               dynamic_coord_sys_;
  CCoordSys             template_coord_sys_;
  std::vector<tstring>  lines_;
  std::vector<tstring>  arcs_;
  std::vector<tstring>  boxs_;
  std::vector<tstring>  etchs_;

  template<class Archive>
  void serialize(Archive &ar, const unsigned int version)
  {
    using boost::serialization::make_nvp;
    ar & make_nvp("name",                     name_);
    ar & make_nvp("cmd_name",                 cmd_name_);
    ar & make_nvp("camera",                   camera_);
    ar & make_nvp("model",                    model_);
    ar & make_nvp("gain",                     gain_);
    ar & make_nvp("shutter",                  shutter_);
    ar & make_nvp("save_ok",                  save_ok_);
    ar & make_nvp("save_ng",                  save_ng_);
    ar & make_nvp("num_oks",                  num_oks_);
    ar & make_nvp("num_ngs",                  num_ngs_);
    ar & make_nvp("num_max_to_save",          num_max_to_save_);
    ar & make_nvp("min_save_interval",        min_save_interval_);
    ar & make_nvp("save_always_from_serial",  save_always_from_serial_);
    ar & make_nvp("save_format",              save_format_);
    if (version>0) {
      ar & make_nvp("find_model",             find_model_);
    }
    if (version>1) {
      ar & make_nvp("build_coord_sys",        build_coord_sys_);
      ar & make_nvp("dynamic_coord_sys",      dynamic_coord_sys_);
      ar & make_nvp("template_coord_sys",     template_coord_sys_);
    }
    ar & make_nvp("lines",                    lines_);
    ar & make_nvp("arcs",                     arcs_);
    ar & make_nvp("boxs",                     boxs_);
    if (version>2) {
      ar & make_nvp("etchs",                  etchs_);
    }

    if (Archive::is_loading()) {
      CreateImageFolder();
    }
  }
};

BOOST_CLASS_VERSION(CMeasureStation, 3)